﻿using Sunny.UI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using xbd.s7netplus;

namespace lyh.FG2JiaYaZhanDemo
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            Load += MainForm_Load;

            this.timer.Interval = 500;//设置时间间隔为500ms
            this.timer .Tick+=UpdateTime_Tick;
            this.timer.Start();
        }

        private void UpdateTime_Tick(object sender, EventArgs e)
        {
            //用于锁屏
            if (sysInfo.ScreenTime > 0)
            {
                Program.TickCount++;
                if (sysInfo.ScreenTime * 1000 / this.timer.Interval == Program.TickCount)
                {
                    //锁屏
                    SuoPing.LockWorkStation();

                }

            }

            //用于注销,启动用户自动注销功能
            if (sysInfo.LogoffTime > 0)
            {
                if (Program.currentSysAdmin != null)
                { 
                  TimeSpan  timeSpan =DateTime.Now - LoginTime;
                    if (timeSpan.TotalSeconds > sysInfo.LogoffTime)
                    {
                        Program.currentSysAdmin = null;
                        this.button5.Text = "用户登录";
                    }
                }
            }
        }

        #region 成员变量

        private PlcDataService plcDataService = new PlcDataService();

        /// <summary>
        /// 系统配置文件路径
        /// </summary>
        private string sysInfoPath = Application.StartupPath + "\\Sysinfo.ini";

        /// <summary>
        /// 系统配置文件服务对象
        /// </summary>
        private SysInfoServer sysInfoServer = new SysInfoServer();

        /// <summary>
        /// 系统配置对象
        /// </summary>
        private SysInfo sysInfo = null;

        /// <summary>
        /// 可以用来取消异步操作。用于断网重新连接
        /// </summary>
        private CancellationTokenSource cts = new CancellationTokenSource();

        /// <summary>
        /// 是否第一次扫描，用于第一次让按钮与控件的状态同步，这样系统UI更新时就不需要扫描pump的状态，而是当值改变的时候才更新
        /// </summary>
        private bool isFirstScan = true;

        /// <summary>
        /// 定时器
        /// </summary>
        private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();

        /// <summary>
        /// 也是负责锁屏的对象，当有鼠标操作时，会调用这个对象的锁屏方法
        /// </summary>
        private MessageFilter messageFilter = new MessageFilter();

        /// <summary>
        /// 当前登录时间
        /// </summary>
        private DateTime LoginTime = DateTime.Now;
        
        #endregion

        #region 窗体加载事件
        private void MainForm_Load(object sender, EventArgs e)
        {

            this.sysInfo = sysInfoServer.GetSysInfoFromPath(sysInfoPath);
            if (sysInfo == null)
            {
                UIMessageBox.ShowError("系统配置加载失败！");
                return;
            }

            Task.Run(new Action(() =>
            {
                PLCCommunication();
            }
            ));

            //也是用于锁屏的对象，当有鼠标操作时，会调用这个对象的锁屏方法
            if (sysInfo.ScreenTime > 0)
            { 
                Application.AddMessageFilter(messageFilter);//当有鼠标操作时，不会锁屏
            
            }

        }
        #endregion

        #region 更新label时间
        private void UpdateLabelOnMainThread()
        {
            // 使用 Invoke 方法确保在主线程上更新 label2
            if (this.label2.InvokeRequired)
            {
                this.label2.Invoke(new Action(() =>
                {
                    this.label2.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " " + new CultureInfo("zh-CN").DateTimeFormat.GetDayName(DateTime.Now.DayOfWeek);
                }));
            }
            else
            {
                this.label2.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " " + new CultureInfo("zh-CN").DateTimeFormat.GetDayName(DateTime.Now.DayOfWeek);
            }
        }

        #endregion

        #region 多线程方法体，与PLC实时通信，可以支持断网重新连接
        /// <summary>
        /// 多线程方法体，与PLC实时通信，可以支持断网重新连接
        /// </summary>
        private void PLCCommunication()
        {

            while (!cts.IsCancellationRequested)
            {
                //Debug.WriteLine("plcDataService.IsConnected:  "+ plcDataService.IsConnected.ToString());
                //星期几
                UpdateLabelOnMainThread();

                if (plcDataService.IsConnected)
                {
                    this.uiLight1.State = UILightState.On;
                    this.BackColor = Color.FromArgb(9, 9, 45);
                    var data = plcDataService.ReadPlcData();

                    if (data.IsSuccess)
                    {
                        plcDataService.ErrorTimes = 0;

                        //更新显示
                        this.UpDataUiData(data.Content);
                    }
                    else
                    {
                        //容错次数
                        plcDataService.ErrorTimes++;
                        if (plcDataService.ErrorTimes > plcDataService.AllowErrorTimes)
                        {
                            plcDataService.IsConnected = false;
                        }
                    }
                    Thread.Sleep(300);
                }
                else
                {
                    this.uiLight1.State = UILightState.Off;
                    this.BackColor = Color.DarkGray;
                    //如果是第一次扫描，直接连接
                    //如果不是第一次扫描，先断开再连接
                    if (!plcDataService.IsFirstScan)
                    {
                        Thread.Sleep(1000);
                        //断开连接
                        plcDataService.DisConnect();
                    }
                    else
                    {
                        plcDataService.IsFirstScan = false;
                    }

                    //重新连接
                    xbd.DataConvertLib.OperateResult result = plcDataService.Connect(this.sysInfo);
                    plcDataService.IsConnected = result.IsSuccess;
                    isFirstScan = true;
                }
            }
        }
        #endregion

        #region 无边框拖动 
        private Point mPoint;
        private void Panel_MouseDown(object sender, MouseEventArgs e)
        {
            mPoint = new Point(e.X, e.Y);
        }
        private void Panel_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.Location = new Point(this.Location.X + e.X - mPoint.X, this.Location.Y + e.Y - mPoint.Y);
            }
        }
        #endregion

        #region 窗体关闭前取消与该 CancellationTokenSource 相关的所有异步操作。
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            //这行代码的作用是检查 cts 是否为 null，如果不为 null，则调用 cts.Cancel() 方法来取消与该 CancellationTokenSource 相关的所有异步操作。
            cts?.Cancel();//if (cts != null) cts.Cancel();
        }
        #endregion

        #region 更新UI界面数据
        /// <summary>
        /// 更新UI界面数据
        /// </summary>
        /// <param name="plcData"></param>
        private void UpDataUiData(PlcData plcData)
        {
            //用try是当关闭窗体时，异步线程可能还会执行
            try
            {
                if (this.InvokeRequired)//如果当前线程不是窗体的线程
                {
                    this.Invoke(new Action<PlcData>(UpDataUiData), plcData);
                }
                else
                {
                    if (isFirstScan)
                    {
                        this.uiSwitch1.Active = plcData.InPump2State;
                        this.uiSwitch2.Active = plcData.InPump1State;
                        this.uiSwitch3.Active = plcData.CirclePump1State;
                        this.uiSwitch4.Active = plcData.CirclePump2State;
                        this.xbdPump1.IsRun = plcData.InPump1State;
                        this.xbdPump2.IsRun = plcData.InPump2State;
                        this.xbdMotor1.PumpState = plcData.CirclePump1State ? xbd.ControlLib.PumpState.运行 : xbd.ControlLib.PumpState.停止;//循环泵
                        this.xbdMotor2.PumpState = plcData.CirclePump2State ? xbd.ControlLib.PumpState.运行 : xbd.ControlLib.PumpState.停止;

                        this.uiValve1.Active = plcData.ValveInState;//进水阀门
                        this.uiValve2.Active = plcData.ValveOutState;//出水阀门
                        isFirstScan = false;

                    }
                    //this.xbdPump1.IsRun = plcData.InPump1State;
                    //this.uiSwitch2.Active = plcData.InPump1State;
                    //this.xbdPump2.IsRun = plcData.InPump2State;
                    //this.uiSwitch1.Active = plcData.InPump2State;

                    //this.xbdMotor1.PumpState = plcData.CirclePump1State ? xbd.ControlLib.PumpState.运行 : xbd.ControlLib.PumpState.停止;//循环泵
                    //this.xbdMotor2.PumpState = plcData.CirclePump2State ? xbd.ControlLib.PumpState.运行 : xbd.ControlLib.PumpState.停止;
                    //this.uiSwitch3.Active = plcData.CirclePump1State;
                    //this.uiSwitch4.Active = plcData.CirclePump2State;

                    //this.uiValve1.Active = plcData.ValveInState;//进水阀门
                    //this.uiValve2.Active = plcData.ValveOutState;//出水阀门
                    this.uiValve1.ValveColor = plcData.ValveInState ? Color.FromArgb(80, 160, 255) : Color.Red;
                    this.uiValve2.ValveColor = plcData.ValveOutState ? Color.FromArgb(80, 160, 255) : Color.Red;



                    this.meterControl1.MeterValue = plcData.PressureIn;//进水压力            
                    this.meterControl2.MeterValue = plcData.PressureOut;//出水压力
                    this.meterControl3.MeterValue = plcData.TempIn1;//1#进水管温度
                    this.meterControl4.MeterValue = plcData.TempIn2;//2#进水管温度
                    this.meterControl5.MeterValue = plcData.TempOut;//出水管温度
                    this.meterControl6.MeterValue = plcData.PressureTank1;
                    this.meterControl7.MeterValue = plcData.PressureTank2;
                    this.xbdWave1.Value = Convert.ToInt32((plcData.LevelTank1 / 2.0f) * 100);
                    this.xbdWave2.Value = Convert.ToInt32((plcData.LevelTank2 / 2.0f) * 100);
                    this.meterControl8.MeterValue = plcData.PressureTankOut;

                    this.label13.Text = plcData.PressureTank1.ToString("f2");
                    this.label20.Text = plcData.PressureTank2.ToString("f2");
                    this.label22.Text = plcData.PressureOut.ToString("f2");
                    this.label19.Text = plcData.LevelTank1.ToString("f2");
                    this.label21.Text = plcData.LevelTank1.ToString("f2");

                    this.uiLight2.State = !plcData.SysRunState ? UILightState.On : UILightState.Off;
                    this.uiLight3.State = !plcData.SysAlarmState ? UILightState.On : UILightState.Off;

                    this.uiDigitalLabel1.Value = plcData.TempIn1;
                    this.uiDigitalLabel2.Value = plcData.TempIn2;
                    this.uiDigitalLabel3.Value = plcData.TempOut;
                    this.uiDigitalLabel4.Value = plcData.PressureOut;

                }
            }
            catch (Exception ex)
            {
                return;
            }
        }
        #endregion

        #region 按钮事件
        /// <summary>
        /// 打开参数设置界面
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_paramset_Click(object sender, EventArgs e)
        {
            new FrmParamSet(this.sysInfo, this.sysInfoServer, this.sysInfoPath).Show();

        }

        /// <summary>
        /// 退出程序
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button6_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// 系统复位
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            plcDataService.SysReset();
        }

        #endregion

        #region 循环泵控制


        private void uiSwitch3_ValueChanged(object sender, bool value)
        {
            bool re = true;
            if (this.uiSwitch3.Active)//启动
            {
                var result = MessageBox.Show("确定要打开循环泵1吗？", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
                if (result == DialogResult.Cancel)
                {
                    this.uiSwitch3.ValueChanged -= uiSwitch3_ValueChanged;
                    this.uiSwitch3.Active = !this.uiSwitch3.Active;
                    this.uiSwitch3.ValueChanged += uiSwitch3_ValueChanged;

                }
                else
                {
                    re &= plcDataService.CirclePump1Control(true);
                }
            }
            else//停止
            {
                var result = MessageBox.Show("确定要停止循环泵1吗？", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
                if (result == DialogResult.Cancel)
                {
                    this.uiSwitch3.ValueChanged -= uiSwitch3_ValueChanged;
                    this.uiSwitch3.Active = !this.uiSwitch3.Active;
                    this.uiSwitch3.ValueChanged += uiSwitch3_ValueChanged;
                }
                else
                {
                    re &= plcDataService.CirclePump1Control(false);
                }

            }
            if (!re)
            {
                this.uiSwitch3.ValueChanged -= uiSwitch3_ValueChanged;
                this.uiSwitch3.Active = !this.uiSwitch3.Active;
                this.uiSwitch3.ValueChanged += uiSwitch3_ValueChanged;
                UIMessageTip.ShowError("操作失败！");
            }
            if (re)
            {
                UIMessageTip.ShowOk("操作成功！");
            }
            this.xbdMotor1.PumpState = this.uiSwitch3.Active ? xbd.ControlLib.PumpState.运行 : xbd.ControlLib.PumpState.停止;
        }

        private void uiSwitch4_ValueChanged(object sender, bool value)
        {
            //value其实就是uiSwitch4.Active 
            if (!plcDataService.CirclePump2Control(value))
            {
                this.uiSwitch4.ValueChanged -= uiSwitch4_ValueChanged;
                this.uiSwitch4.Active = !this.uiSwitch4.Active;
                this.uiSwitch4.ValueChanged += uiSwitch4_ValueChanged;
            }
            this.xbdMotor2.PumpState = this.uiSwitch4.Active ? xbd.ControlLib.PumpState.运行 : xbd.ControlLib.PumpState.停止;
        }

        private void uiSwitch1_ValueChanged(object sender, bool value)
        {
            //plcDataService.InPump2Control(value)

            //不用上面的方法做的原因是，如果上面的方法执行失败，则uiSwitch2的状态会反复改变，这样会一直调用uiSwitch2_ValueChanged函数，造成死循环。
            if (!plcDataService.InPump2Control(value))
            {
                this.uiSwitch1.ValueChanged -= uiSwitch1_ValueChanged;
                this.uiSwitch1.Active = !this.uiSwitch2.Active;
                this.uiSwitch1.ValueChanged += uiSwitch1_ValueChanged;
            }
            xbdPump2.IsRun = this.uiSwitch1.Active;
        }

        private void uiSwitch2_ValueChanged(object sender, bool value)
        {
            if (!plcDataService.InPump1Control(value))
            {
                this.uiSwitch2.ValueChanged -= uiSwitch2_ValueChanged;
                this.uiSwitch2.Active = !this.uiSwitch2.Active;
                this.uiSwitch2.ValueChanged += uiSwitch2_ValueChanged;
            }
            xbdPump1.IsRun = this.uiSwitch2.Active;
        }

        /// <summary>
        /// 进出水阀门控制
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Common_DoubleClick(object sender, EventArgs e)
        {
            UIValve control = sender as UIValve;
            bool re = !control.Active;
            if (re)
            {
                var mess1 = MessageBox.Show("确定要打开阀门吗？", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
                if (mess1 == DialogResult.Cancel)
                {
                    return;
                }
                else
                {
                    //control.Active = true;
                    control.ValveColor = Color.FromArgb(80, 160, 255);
                    if (control.Tag == "进水阀")
                    { plcDataService.ValveInControl(true); }
                    else
                    {
                        plcDataService.ValveOutControl(true);
                    }
                }
            }
            else
            {
                var mess1 = MessageBox.Show("确定要关闭阀门吗？", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
                if (mess1 == DialogResult.Cancel)
                {
                    return;
                }
                else
                {
                    //control.Active =false;
                    control.ValveColor = Color.Red;
                    if (control.Tag == "进水阀")
                    { plcDataService.ValveInControl(false); }
                    else
                    {
                        plcDataService.ValveOutControl(false);
                    }

                }
            }
        }



        #endregion


    }
}